package shopping

import (
    "time"
    "strconv"
	"encoding/json"
	"dhfshop/utils/math"
	"dhfshop/models/shopping"
	"dhfshop/models/misc"
	"dhfshop/models/isv"
	"dhfshop/models/member"
	"dhfshop/domain/member"
	"dhfshop/domain/pay"
	"dhfshop/service/event"
	"dhfshop/controllers/base"
	"github.com/astaxie/beego/validation"
	wxpay "wxsdk/wxpay/wxapp"
	"github.com/astaxie/beego"
	"dhfshop/service/nsqcli"
)

// 退款管理
type RefundController struct {
	base.BaseController
}

func (this *RefundController) RefundAdd() {
	var (
	    paymentId   string
		totalFeeStr string
		payFeeStr   string
	    refundRsp   *wxpay.RefundResponse
		actFee      float32
	)
	//operatorUserId := int64(this.Ctx.Input.GetData("curUserId").(int))   //商家ID
	v := struct {
		OrderIdStr  string  `form:"order_id"  valid:"Required"`
	    Fee         float32 `form:"fee"`
	}{}
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return
	}
	orderId, err := strconv.ParseInt(v.OrderIdStr, 10, 64)
	if err != nil {
	    this.ServeError("ParseInt: " + err.Error())
		return
	}
	orders, err := shopping.GetOrderById(orderId)
	if err != nil {
	    this.ServeError("GetOrderById: " + err.Error())
		return
	}
	if orders.Status != "S_ORDER_AFTER_SERVICE" {
	   this.ServeError("This status can not refund:" + orders.Status)
	   return 
	}
	payment, err := shopping.GetPaymentListByOrderId(orderId)
	if err != nil {
		this.ServeError("GetPaymentListByOrderId: " + err.Error())
		return
	}
	if v.Fee > payment.PayFee {
		this.ServeError("退款金额不能大于所支付金额")
		return
	}
	if v.Fee > 0 {
		actFee = v.Fee
	}else {
		if payment.CashFee > 0 {
		   actFee = payment.PayFee
		} else {
		   actFee = payment.PayFee
		}
	}
	if orders.PayWayCode == 1 {  //微信退款
		acPay, err := isv.GetParamsByAppIdOrSubAppId(payment.AppId)
		if err != nil {
			this.ServeError("GetParamsByAppIdOrSubAppId: " + err.Error())
			return
		}
		totalFeeStr = strconv.FormatInt(math.MultiTotalPriceInt(payment.PayFee, 100), 10)
		payFeeStr = strconv.FormatInt(math.MultiTotalPriceInt(actFee, 100), 10)
		//beego.Debug("pay_params_id:", acPay.PayParamsId,"payFeeStr:", payFeeStr)
		refundNo, _:= misc.GetBillNo("PA")
		if payment.MchTypeId == 1 {
		    refundRsp, err = wxpay.Refund(acPay.AppId,acPay.MchId,"","",acPay.Appkey,
									   "",v.OrderIdStr,refundNo,totalFeeStr,payFeeStr,acPay.PemCert,acPay.PemKey)
			if err != nil {
				this.ServeError("Refund:" + v.OrderIdStr + " " + err.Error())
				return 
			}
		}else if payment.MchTypeId == 2 {
		    pemCertFile := "conf/apiclient_cert.pem"
			pemKeyFile := "conf/apiclient_key.pem"
		    refundRsp, err = wxpay.RefundOnCertFile(acPay.AppId,acPay.MchId,acPay.SubAppId,acPay.SubMchId,acPay.Appkey,
									   "",v.OrderIdStr,refundNo,payFeeStr,payFeeStr,pemCertFile,pemKeyFile)
			if err != nil {
				this.ServeError("RefundOnCertFile:" + v.OrderIdStr + " " + err.Error())
				return 
			}
		} else {
		    this.ServeError("mch types is not supported")
	        return 
		}
		var payFee float32 = 0.0
		var cashFee float32 = 0.0
		var couponFee float32 = 0.0
		var srcData string
        orderId, _:= strconv.ParseInt(refundRsp.OutTradeNo, 10, 64)
		if payFeeTmp, err := strconv.ParseFloat(refundRsp.RefundFee, 32); err == nil {   
			payFee = math.DivTotalFee(float32(payFeeTmp), 100)  //微信返回的金额需要除以100
		}
		if payFeeTmp, err := strconv.ParseFloat(refundRsp.CashRefundFee, 32); err == nil {   
			cashFee = math.DivTotalFee(float32(payFeeTmp), 100)  //微信返回的金额需要除以100
		}
		if payFeeTmp, err := strconv.ParseFloat(refundRsp.CouponRefundFee, 32); err == nil {   
			couponFee = math.DivTotalFee(float32(payFeeTmp), 100)  //微信返回的金额需要除以100
		}
		if msgBody, err := json.Marshal(refundRsp); err == nil {
		   srcData = string(msgBody)
		}
		mchTypeId := 1
		appId := refundRsp.AppId
		if len(refundRsp.SubMchId) > 0 {
		   mchTypeId = 2
		   appId = refundRsp.SubAppId
		}
		tmpId, err := shopping.AddPaymentByPayMsg(orders.PartnerId,orders.StoreId,orders.MemberId,orderId,3,
                        "1",refundRsp.TransactionId,refundRsp.FeeType,
						appId,acPay.MchId,refundNo,srcData,payFee,cashFee,couponFee,mchTypeId)
		if err != nil {
			this.ServeError("AddPaymentByWxRefund:" + err.Error())
			return
		}
		paymentId = tmpId
		
	}else if orders.PayWayCode == 2 {  //余额支付,直接退回到余额
		if balanceLog, err := member.GetBalanceLogByOutOuterNo(v.OrderIdStr); err == nil {
		    oldAccount, err := member.GetAccountById(orders.MemberId)
			if err != nil {
				this.ServeError("GetAccountById:" + err.Error())
				return
			}
			if _, err = memberlayer.AddBalance(orders.PartnerId,orders.MemberId,oldAccount,balanceLog.IncBalance,balanceLog.IncPresent,v.OrderIdStr,1); err != nil {
				this.ServeError("AddBalance:" + err.Error())
				return
			}
		} else {
		    this.ServeError("没有找到合法的支付记录,order_id: " + v.OrderIdStr)
	        return 
		}
	} else if orders.PayWayCode == 9 {
		paymentId, err = paylayer.RoyalRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 10 {
		paymentId, err = paylayer.YabandRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 11 {
		paymentId, err = paylayer.SuperPayRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 12 {
		paymentId, err = paylayer.UsagmsRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 13 {
		paymentId, err = paylayer.DahlRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 14 {
		paymentId, err = paylayer.WiseCashierRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 15 {
		paymentId, err = paylayer.MegaezgoRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 16 {
		paymentId, err = paylayer.ChinaUmsRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee,orders.AccountJson)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 17 {
		paymentId, err = paylayer.OceanPayRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 18 {
		paymentId, err = paylayer.QcurePayRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 20 {
		paymentId, err = paylayer.HnapayRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 21 {
		paymentId, err = paylayer.AllInPayRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 22 {
		paymentId, err = paylayer.GpslRefund(orders.AppId,orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
		if err != nil {
		   this.ServeError(err.Error())
		   return
		}
	} else if orders.PayWayCode == 100 {  //积分支付,直接退回到积分中
		if integralLog, err := member.GetIntegralLogByOuterNo(v.OrderIdStr); err == nil {
		    oldAccount, err := member.GetAccountById(orders.MemberId)
			if err != nil {
				this.ServeError("GetAccountById:" + err.Error())
				return
			}
			if _, err = memberlayer.AddIntegral(orders.PartnerId,orders.MemberId,oldAccount,integralLog.IncIntegral,""); err != nil {
				this.ServeError("AddIntegral:" + err.Error())
				return
			}
		} else {
		    this.ServeError("没有找到合法的支付记录,order_id: " + v.OrderIdStr)
	        return 
		}
	} else {
	    this.ServeError("refund types is not supported")
	    return 
	}
	//
	var result string = ""
	var req = new(event.TradeMsg)
	req.CompanyId = orders.PartnerId
	req.UserId = orders.MemberId
	req.OrderId = orderId
	req.MsgHeader.EventType = "E_ORDER_REFUND"
	message, err := event.EncodeMsg(req)
	if err != nil {
        beego.Debug("order_id:", v.OrderIdStr, err.Error())
		this.ServeError(err.Error())
		return      
    }
	event.KernelBus.Publish("E_ORDER_REFUND",message,&result)
	if len(result) > 0 {
		beego.Debug("order_id:", v.OrderIdStr, result)
		this.ServeError(result)
		return
	}
	paylayer.ReturnStocks(orders)
	account, err := member.GetAccountById(int64(orders.MemberId))
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	memberlayer.UpdateAccountForRefund(orders.PartnerId,orders.MemberId,account,orders.Payment,1)
	rsp := struct {
	    OrderIdStr   string   `json:"order_id"`
	    PaymentId    string   `json:"payment_id"`
	}{OrderIdStr: v.OrderIdStr, PaymentId: paymentId}
	
	sendRefundSuccessMsg(orders.PartnerId,orders.StoreId,orders.MemberId,orderId,actFee)
	
	this.Data["json"] = rsp
	this.ServeJSON()
}

func sendRefundSuccessMsg(partnerId, storeId, memberId, orderId int64,payment float32) {
	refundSuccessNsq := struct {
		PartnerId string `json:"partner_id"`
		StoreId   string `json:"store_id"`
		MemberId  string `json:"member_id"`
		Types     string `json:"type"`
		OrderId   string `json:"order_id"`
		Payment   float32 `json:"payment"`
		OrderTime int64  `json:"order_time"`
	}{Types:"refund"}
	refundSuccessNsq.PartnerId = strconv.FormatInt(partnerId, 10)
	refundSuccessNsq.StoreId = strconv.FormatInt(storeId, 10)
	refundSuccessNsq.MemberId = strconv.FormatInt(memberId, 10)
	refundSuccessNsq.OrderId = strconv.FormatInt(orderId, 10)
	refundSuccessNsq.Payment = payment
	refundSuccessNsq.OrderTime = time.Now().UTC().Unix()
	if b, err := json.Marshal(refundSuccessNsq); err == nil {
		//beego.Debug("OrderCollection msg:", string(b))
		address := beego.AppConfig.String("NsqUrl")
		topic := "OrderCollection"
		if err = nsqcli.StartProducer(address, topic, b); err != nil {
			beego.Debug("StartProducer err:", err.Error())
		}
	}
}


func (this *RefundController) RefundCommonAdd() {
	var (
	    paymentId   string
		totalFeeStr string
		payFeeStr   string
	    refundRsp   *wxpay.RefundResponse
		actFee      float32
	)
	//operatorUserId := int64(this.Ctx.Input.GetData("curUserId").(int))   //商家ID
	v := struct {
		OrderIdStr  string  `form:"order_id"  valid:"Required"`
	    Fee         float32 `form:"fee"`
	}{}
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return
	}
	orderId, err := strconv.ParseInt(v.OrderIdStr, 10, 64)
	if err != nil {
	    this.ServeError("ParseInt: " + err.Error())
		return
	}
	payment, err := shopping.GetPaymentListByOrderId(orderId)
	if err != nil {
		this.ServeError("GetPaymentListByOrderId: " + err.Error())
		return
	}
	if v.Fee > payment.PayFee {
		this.ServeError("退款金额不能大于所支付金额")
		return
	}
	if v.Fee > 0 {
		actFee = v.Fee
	}else {
		if payment.CashFee > 0 {
		   actFee = payment.PayFee
		} else {
		   actFee = payment.PayFee
		}
	}
	acPay, err := isv.GetParamsByAppIdOrSubAppId(payment.AppId)
	if err != nil {
		this.ServeError("GetParamsByAppIdOrSubAppId: " + err.Error())
		return
	}
	totalFeeStr = strconv.FormatInt(math.MultiTotalPriceInt(payment.PayFee, 100), 10)
	payFeeStr = strconv.FormatInt(math.MultiTotalPriceInt(actFee, 100), 10)
	//beego.Debug("pay_params_id:", acPay.PayParamsId,"payFeeStr:", payFeeStr)
	refundNo, _:= misc.GetBillNo("PA")
	if payment.MchTypeId == 1 {
		refundRsp, err = wxpay.Refund(acPay.AppId,acPay.MchId,"","",acPay.Appkey,
								   "",v.OrderIdStr,refundNo,totalFeeStr,payFeeStr,acPay.PemCert,acPay.PemKey)
		if err != nil {
			this.ServeError("Refund:" + v.OrderIdStr + " " + err.Error())
			return 
		}
	}else if payment.MchTypeId == 2 {
		pemCertFile := "conf/apiclient_cert.pem"
		pemKeyFile := "conf/apiclient_key.pem"
		refundRsp, err = wxpay.RefundOnCertFile(acPay.AppId,acPay.MchId,acPay.SubAppId,acPay.SubMchId,acPay.Appkey,
								   "",v.OrderIdStr,refundNo,payFeeStr,payFeeStr,pemCertFile,pemKeyFile)
		if err != nil {
			this.ServeError("RefundOnCertFile:" + v.OrderIdStr + " " + err.Error())
			return 
		}
	} else {
		this.ServeError("mch types is not supported")
		return 
	}
	var payFee float32 = 0.0
	var cashFee float32 = 0.0
	var couponFee float32 = 0.0
	var srcData string
	if payFeeTmp, err := strconv.ParseFloat(refundRsp.RefundFee, 32); err == nil {   
		payFee = math.DivTotalFee(float32(payFeeTmp), 100)  //微信返回的金额需要除以100
	}
	if payFeeTmp, err := strconv.ParseFloat(refundRsp.CashRefundFee, 32); err == nil {   
		cashFee = math.DivTotalFee(float32(payFeeTmp), 100)  //微信返回的金额需要除以100
	}
	if payFeeTmp, err := strconv.ParseFloat(refundRsp.CouponRefundFee, 32); err == nil {   
		couponFee = math.DivTotalFee(float32(payFeeTmp), 100)  //微信返回的金额需要除以100
	}
	if msgBody, err := json.Marshal(refundRsp); err == nil {
	   srcData = string(msgBody)
	}
	mchTypeId := 1
	appId := refundRsp.AppId
	if len(refundRsp.SubMchId) > 0 {
	   mchTypeId = 2
	   appId = refundRsp.SubAppId
	}
	tmpId, err := shopping.AddPaymentByPayMsg(payment.PartnerId,payment.StoreId,payment.MemberId,orderId,3,
					"1",refundRsp.TransactionId,refundRsp.FeeType,
					appId,acPay.MchId,refundNo,srcData,payFee,cashFee,couponFee,mchTypeId)
	if err != nil {
		this.ServeError("AddPaymentByWxRefund:" + err.Error())
		return
	}
	paymentId = tmpId
	sendRefundSuccessMsg(payment.PartnerId,payment.StoreId,payment.MemberId,orderId,actFee)
	rsp := struct {
	    OrderIdStr   string   `json:"order_id"`
	    PaymentId    string   `json:"payment_id"`
	}{OrderIdStr: v.OrderIdStr, PaymentId: paymentId}
	this.Data["json"] = rsp
	this.ServeJSON()
}
